<template>
  <div class="portal-design-box">
    <div class="center-box">
      <div class="action-box">
        <div v-for="(item, listIndex) in componentsList" :key="listIndex" class="components-part">
          <a-dropdown placement="bottom">
            <div class="components-title">{{ item.title }}<i class="icon-ym icon-ym-arrow-down"></i></div>
            <template #overlay>
              <a-menu class="components-menu">
                <a-menu-item class="components-item" v-for="(element, index) in item.list" :key="index" @click="handleAddComponent(element)">
                  <i :class="element.icon"></i>
                  {{ element.label }}
                </a-menu-item>
              </a-menu>
            </template>
          </a-dropdown>
        </div>
      </div>
      <ScrollContainer class="layout-area">
        <div v-if="showType == 'pc'">
          <grid-layout :layout.sync="layout" :row-height="40" v-if="layout.length">
            <grid-item
              v-for="item in layout"
              :x="item.x"
              :y="item.y"
              :w="item.w"
              :h="item.h"
              :i="item.i"
              :key="item.i"
              :maxH="item.maxH"
              :minH="item.minH"
              :minW="item.minW"
              :maxW="item.maxW"
              :class="{ 'active-item': item.i === activeId }"
              @resized="resizedEvent(item.i, item)"
              @moved="movedEvent"
              @click="handleClick(item)">
              <Parser :item="item" :activeId="activeId" />
              <div class="mask" v-if="!noNeedMaskList.includes(item.gentleKey)"></div>
              <span title="复制" class="drawing-item-copy" @click="handleAddComponent(item, 'copy')">
                <copy-outlined />
              </span>
              <a-popconfirm title="确定删除该组件？" class="drawing-item-delete" @confirm="handleRemoveItem(item.i)">
                <span title="删除">
                  <delete-outlined />
                </span>
              </a-popconfirm>
            </grid-item>
          </grid-layout>
          <div v-show="!layout.length" class="empty-info">
            <img src="../../../../assets/images/emptyPortal.png" class="empty-img" />
          </div>
        </div>
        <div id="ipad" v-else>
          <div class="outer-ipad">
            <div class="ipad-body">
              <div class="ipad-name">当前展示pc设计内容，请前往APP查看效果</div>
              <ScrollContainer class="center-scrollbar">
                <draggable v-if="layout.length" class="drawing-board" :list="layout" :animation="340" group="componentsGroup" item-key="i">
                  <template #item="{ element }">
                    <div class="item-box m-10px portal-tabs-box" @click="handleClick(element)" :class="{ 'active-item': element.i === activeId }">
                      <Parser :item="element" :activeId="activeId" :showType="showType" />
                      <div class="mask" v-if="!noNeedMaskList.includes(element.gentleKey)"></div>
                      <span title="复制" class="drawing-item-copy" @click="handleAddComponent(element)">
                        <copy-outlined />
                      </span>
                      <a-popconfirm title="确定删除该组件？" class="drawing-item-delete" @confirm="handleRemoveItem(element.i)">
                        <span title="删除">
                          <delete-outlined />
                        </span>
                      </a-popconfirm>
                    </div>
                  </template>
                </draggable>
                <div v-show="!layout.length" class="empty-info app-empty-info">
                  <img src="../../../../assets/images/emptyPortal.png" class="empty-img" />
                </div>
              </ScrollContainer>
            </div>
          </div>
        </div>
      </ScrollContainer>
    </div>
    <RightPanel :active-data="activeData" :refresh="refresh" :showType="showType" @relationChange="onRelationChange" />
    <PreviewModal @register="registerPreview" />
  </div>
</template>
<script lang="ts" setup>
  import { onMounted, reactive, toRefs, nextTick, inject } from 'vue';
  import { ScrollContainer } from '/@/components/Container';
  import RightPanel from './RightPanel.vue';
  import { layoutComponents, systemComponents, basicComponents, chartComponents } from '../helper/componentMap';
  import { noNeedMaskList, needDefaultList, chartData, mapChartData, rankList, timeAxisList, tableList } from '../helper/dataMap';
  import { CopyOutlined, DeleteOutlined } from '@ant-design/icons-vue';
  import draggable from 'vuedraggable';
  import Parser from './Parser.vue';
  import { useMessage } from '/@/hooks/web/useMessage';
  import { useModal } from '/@/components/Modal';
  import PreviewModal from './Preview.vue';
  import { isUrl } from '/@/utils/is';
  import { useI18n } from '/@/hooks/web/useI18n';

  interface State {
    componentsList: any[];
    layout: any[];
    refresh: any;
    config: any;
    copyDrawingList: string;
    activeId: string;
    activeData: any;
  }

  const state = reactive<State>({
    componentsList: [
      { title: '布局控件', list: layoutComponents },
      { title: '基础控件', list: basicComponents },
      { title: '系统控件', list: systemComponents },
      { title: '图表控件', list: chartComponents },
    ],
    layout: [],
    refresh: {},
    config: {},
    copyDrawingList: '',
    activeId: '',
    activeData: null,
  });
  const { componentsList, refresh, activeId, activeData, layout } = toRefs(state);
  const defaultConf = {
    layoutId: 100,
    layout: [],
    refresh: {
      autoRefresh: false,
      autoRefreshTime: '5',
    },
  };
  defineExpose({ getData, empty, handleData, preview });
  const emitter: any = inject('emitter');
  const { t } = useI18n();
  const props = defineProps(['conf', 'showType']);
  const emit = defineEmits(['register', 'addRecord']);
  const { createConfirm } = useMessage();
  const [registerPreview, { openModal: openPreviewModal }] = useModal();

  function init() {
    if (typeof props.conf === 'object' && props.conf !== null) {
      state.config = { ...defaultConf, ...props.conf };
    } else {
      state.config = JSON.parse(JSON.stringify(defaultConf));
      state.config.layoutId = 100;
    }
    state.layout = state.config.layout || [];
    state.refresh = state.config.refresh || {};
    setTimeout(() => {
      addLocalRecord(state.layout);
      setActiveData();
    }, 50);
    emitter.on('addComponent', data => {
      handleAddComponent(data.val, '', data.item);
    });
    emitter.on('handlerActive', val => {
      handleClick(val);
    });
  }
  function handleAddComponent(item, type?, currentItem?) {
    let clone = JSON.parse(JSON.stringify(item));
    let x = 0,
      y = 0,
      i = state.config.layoutId;
    if (state.layout.length) {
      let maxYItem = { y: 0, h: 0 };
      for (let i = 0; i < state.layout.length; i++) {
        if (state.layout[i].y >= maxYItem.y) maxYItem = state.layout[i];
      }
      y = maxYItem.y + maxYItem.h;
    }
    let row = { ...clone, i, x, y };
    if (needDefaultList.includes(row.gentleKey) && type != 'copy') row.option.defaultValue = getDefaultValue(row);
    if (currentItem) {
      if (currentItem.gentleKey == 'card') currentItem.children = [row];
      if (currentItem.gentleKey == 'tab') {
        for (let i = 0; i < currentItem.children.length; i++) {
          const element = currentItem.children[i];
          if (element.name == currentItem.active) currentItem.children[i].children = [row];
        }
      }
    } else {
      state.layout.push(row);
    }
    state.activeId = state.config.layoutId;
    state.activeData = row;
    state.config.layoutId++;
    addLocalRecord(state.layout);
  }
  function getDefaultValue(row) {
    const gentleKey = row.gentleKey;
    if (gentleKey == 'text') return '快速开发平台';
    if (gentleKey == 'image') return 'https://ginfo.gentlesoft.com.cn/data/file/lowcode.png';
    if (gentleKey == 'video') return 'https://prod-streaming-video-msn-com.akamaized.net/a8c412fa-f696-4ff2-9c76-e8ed9cdffe0f/604a87fc-e7bc-463e-8d56-cde7e661d690.mp4';
    if (gentleKey == 'barChart' || gentleKey == 'lineChart' || gentleKey == 'pieChart') return chartData.baseBarData;
    if (gentleKey == 'radarChart') return chartData.radarData;
    if (gentleKey == 'mapChart') return mapChartData;
    if (gentleKey == 'rankList') return rankList;
    if (gentleKey == 'timeAxis') return timeAxisList;
    if (gentleKey == 'tableList') return tableList;
  }
  function addLocalRecord(val) {
    if (JSON.stringify(val) != state.copyDrawingList) {
      state.copyDrawingList = JSON.stringify(val);
      emit('addRecord', val);
    }
  }
  function setActiveData(i = 0) {
    state.activeId = '';
    state.activeData = {};
    if (state.layout.length) {
      state.activeData = state.layout[i];
      state.activeId = state.layout[i].i;
    }
  }
  function onRelationChange() {}
  function resizedEvent(i, item) {
    emitter.emit('eChart' + i);
    const loop = data => {
      if (data.children && item.children.length) {
        data.children.map(ele => {
          if (ele.gentleKey) emitter.emit('eChart' + ele.i);
          if (ele.children && ele.children.length) loop(ele);
        });
      }
    };
    loop(item);
    addLocalRecord(state.layout);
  }
  function movedEvent() {
    addLocalRecord(state.layout);
  }
  function handleClick(item) {
    state.activeId = item.i;
    state.activeData = item;
  }
  function handleRemoveItem(i) {
    state.layout = state.layout.filter(item => item.i !== i);
    state.activeId = '';
    state.activeData = {};
    addLocalRecord(state.layout);
    nextTick(() => {
      const len = state.layout.length;
      if (len) setActiveData(len - 1);
    });
  }
  function getData() {
    return new Promise((resolve, reject) => {
      const loop = list => {
        for (let i = 0; i < list.length; i++) {
          const e = list[i];
          const option = e.option || {};
          const card = e.card || {};
          if (card.cardRightBtn) {
            if (card.linkType === '1' && !card.urlAddress) {
              reject({ msg: `${e.label}控件“菜单名称”属性不能为空`, target: 1 });
              break;
            }
            if (card.linkType === '2') {
              if (!card.urlAddress) {
                reject({ msg: `${e.label}控件“链接地址”属性不能为空`, target: 1 });
                break;
              }
              if (!isUrl(card.urlAddress)) {
                reject({ msg: '请输入正确的链接地址', target: 1 });
                break;
              }
            }
            if (card.appLinkType === '1' && !card.appUrlAddress) {
              reject({ msg: `${e.label}控件“菜单名称”属性不能为空`, target: 1 });
              break;
            }
            if (card.appLinkType === '2') {
              if (!card.appUrlAddress) {
                reject({ msg: `${e.label}控件“链接地址”属性不能为空`, target: 1 });
                break;
              }
              if (!isUrl(card.appUrlAddress)) {
                reject({ msg: '请输入正确的链接地址', target: 1 });
                break;
              }
            }
          }
          if (option.linkType === '1' && !option.urlAddress) {
            reject({ msg: `${e.label}控件“菜单名称”属性不能为空`, target: 1 });
            break;
          }
          if (option.linkType === '2') {
            if (!option.urlAddress) {
              reject({ msg: `${e.label}控件“链接地址”属性不能为空`, target: 1 });
              break;
            }
            if (!isUrl(option.urlAddress)) {
              reject({ msg: '请输入正确的链接地址', target: 1 });
              break;
            }
          }
          if (option.appLinkType === '1' && !option.appUrlAddress) {
            reject({ msg: `${e.label}控件“菜单名称”属性不能为空`, target: 1 });
            break;
          }
          if (option.appLinkType === '2') {
            if (!option.appUrlAddress) {
              reject({ msg: `${e.label}控件“链接地址”属性不能为空`, target: 1 });
              break;
            }
            if (!isUrl(option.appUrlAddress)) {
              reject({ msg: '请输入正确的链接地址', target: 1 });
              break;
            }
          }
          if ((e.gentleKey == 'video' || e.gentleKey == 'image') && option.styleType == 2) {
            const val = e.gentleKey == 'video' ? '视频' : '图片';
            if (!option.defaultValue) {
              reject({ msg: `${e.label}控件“${val}地址”属性不能为空`, target: 1 });
              break;
            }
            if (!isUrl(option.defaultValue)) {
              reject({ msg: `请输入正确的${val}地址`, target: 1 });
              break;
            }
          }
          if (e.gentleKey == 'iframe') {
            if (!option.defaultValue) {
              reject({ msg: `${e.label}控件“链接地址”属性不能为空`, target: 1 });
              break;
            }
            if (!isUrl(option.defaultValue)) {
              reject({ msg: '请输入正确的链接地址', target: 1 });
              break;
            }
          }
          if (e.children && Array.isArray(e.children)) loop(e.children);
        }
      };
      loop(state.layout);
      state.config.layout = state.layout;
      resolve({ formData: state.config, target: 1 });
    });
  }
  function empty() {
    createConfirm({
      iconType: 'warning',
      title: t('common.tipTitle'),
      content: '确定要清空所有吗？',
      onOk: () => {
        state.layout = [];
        state.config.layoutId = 100;
        state.activeId = '';
        state.activeData = {};
        addLocalRecord(state.layout);
      },
    });
  }
  function handleData(data) {
    state.layout = JSON.parse(JSON.stringify(data));
    state.copyDrawingList = JSON.stringify(state.layout);
    let boo = false;
    const loop = list => {
      for (let i = 0; i < list.length; i++) {
        const e = list[i];
        if (e.i === state.activeId) {
          state.activeData = e;
          state.activeId = e.i;
          boo = true;
        }
        if (e.children && Array.isArray(e.children)) loop(e.children);
      }
    };
    loop(state.layout);
    if (!boo) {
      state.activeData = {};
      state.activeId = '';
    }
  }
  function preview() {
    openPreviewModal(true, { layout: state.layout });
  }

  onMounted(() => init());
</script>
